# coding=utf-8
"""
游戏运行的主函数模块，所有的顶层函数
"""

import time
import math
import sys

import pygame
from pygame.locals import *

from .resource_game import *
from . import setting as st

# 创建一个敌机机型的字典
dict_enemy = {'0': st.ENEMY_1, '1': st.ENEMY_2, '2': st.ENEMY_3}
fps1 = 0  # 开始按钮计数器
fps2 = 0
fps6 = 0
ran3 = 0
num = 0  # 减慢移动的计数器
num_shower = 0  # 创建流星雨的帧数计数器和循环次数的计数器


def main():  # 定义一个游戏运行的主函数
    fps = 0  # 创建帧数计数器
    fps4 = 0
    fps5 = 0
    f = 0
    time1 = time.time()
    buttons = ()  # 登陆界面按钮的元组
    buttons1 = ()  # 用来放结束界面的按钮

    pygame.init()  # 系统初始化
    # 创建一个全屏的屏幕对象
    screen = pygame.display.set_mode((st.SCREEN_WIDTH, st.SCREEN_HIGHT), 0, 32)
    pygame.display.set_caption("星河战争-天宇之游")
    screen.get_rect()  # 获取屏幕矩形
    # 创建一个敌机生成器
    EnemyCreate = enemy_create(screen)
    # 创建一个文字显示效果生成器
    Chars = chars(screen)
    game_before(screen)  # 加入游戏界面元素
    st.GAME_BEFORE = True  # 打开游戏前言开关

    while True:  # 开始游戏主循环
        mouse_x, mouse_y = pygame.mouse.get_pos()  # 获取光标的位置
        if st.GAME_BEFORE:  # 游戏进入前言
            key_quit()  # 检测退出按键
            if fps % st.FRAMES == 0:  # 每过帧数显示一个字
                try:
                    next(Chars)
                except StopIteration:
                    pass
            fps += 1
            if fps == st.WIN_OVER_FRAMES:
                fps = 0  # 计数器还原
                cls()  # 清空子弹、删除、界面元素列表
                buttons = game_load(screen)  # 加入登陆界面元素,返回三个按钮的元组
                bc(k2=True)  # 打开游戏界面控制开关

        elif st.SCREEN_CHANGE:  # 游戏界面控制开关
            # 界面按钮遍历检测
            mc(buttons, mouse_x, mouse_y)
            key_load(screen, mouse_x, mouse_y)  # 按键的控制函数

        elif st.GAME_SAY:  # 游戏前言
            key_quit()  # 检测窗口退出按键
            fps5 += 1
            if fps5 == st.WIN_FONT_FRAMES:
                bc(k4=True)  # 打开战斗界面控制开关
                fps5 = 0  # 计数器还原
                cls()  # 清空子弹、删除、界面元素列表
                beijing_1, hero_me = game_fight(screen)  # 加入游戏元素

        elif st.GAME_FIGHT:  # 进入战斗界面
            # 创建一个开关字典用来指示上下左右方向
            dict_key = {st.KEY_UP: 'up',
                        st.KEY_DOWN: 'down',
                        st.KEY_LEFT: 'left',
                        st.KEY_RIGHT: 'right'
                        }
            buttons = key_fight(screen, hero_me)  # 战斗界面的控制函数
            # 创建敌机随机生成器
            fps += 1
            if st.GAME_MOSHI:  # 判断目前的游戏模式
                ps = st.ENEMY_CREATE1
            else:
                ps = st.ENEMY_CREATE2
            if fps % ps == 0:  # 每循环ps次执行
                enemy_make(screen, EnemyCreate)  # 敌机的生产控制
            boss_make(screen)  # boss飞机的产生
            buff_make()  # buff有效时间控制
            move_make(dict_key, hero_me)  # 通过开关字典控制飞机的移动
            if st.ENEMY_START:  # 在boss飞机出现后才检测
                if boss_die():  # boss是否死光
                    buttons1 = go_game_end(screen)  # 加载结束界面得到按钮

        elif st.GAME_END:  # 进入结束界面
            # 界面按钮遍历检测
            mc(buttons1, mouse_x, mouse_y)
            # 按钮控制
            buttons = key_end(screen, mouse_x, mouse_y)
        # 计算帧数的速度
        time2 = time.time()
        fps4 += 1
        if time2 - time1 >= 1:
            time1 = time2
            print(fps4 - f)
            f = fps4

        loop()  # 元素循环显示和清空
        pygame.display.update()  # 更新屏幕
        time.sleep(0.01)  # 休眠0.01秒


def buttons_control(k1=False, k2=False,
                    k3=False, k4=False, k5=False):
    """所有相关界面的开关管理,全部默认关闭"""
    st.GAME_BEFORE = k1  # 游戏进入前的界面控制开关
    st.SCREEN_CHANGE = k2  # 登陆界面开关
    st.GAME_SAY = k3  # 游戏历史背景开关
    st.GAME_FIGHT = k4  # 战斗界面控制开关
    st.GAME_END = k5  # 游戏结束界面控制开关
bc = buttons_control


def mouse_control(buttons, mouse_x, mouse_y):
    """界面按钮的检测函数"""
    try:
        for button in buttons:  # 将光标的坐标传入对象检测开关是否应该打开
            button.mouse_make(mouse_x, mouse_y)
    except Exception as re:
        print(re)
mc = mouse_control


def key_quit():
    """检测是否按了退出键"""
    for event in pygame.event.get():  # 键盘和鼠标事件的监听
        if event.type == pygame.QUIT:  # 检测是否按了窗口的退出按键
            sys.exit()


def key_end(screen, mouse_x, mouse_y):
    """游戏结束后统计界面的按键控制函数"""
    for event in pygame.event.get():  # 键盘和鼠标事件的监听
        # 检测是否按了窗口的退出按键
        if event.type == pygame.QUIT:
            sys.exit()
        # 判断是否按下了鼠标并且光标在按钮范围内
        elif event.type == pygame.MOUSEBUTTONDOWN:
            if 20 <= mouse_x <= 620:
                print(mouse_x)
                print(mouse_y)
                if 200 <= mouse_y <= 285:  # 按下了下一关按钮
                    # st.GAME_MOSHI = True
                    pass
                elif 350 <= mouse_y <= 435:  # 按下了重新开始按钮
                    bc(k2=True)  # 打开登陆界面开关
                    cls()  # 清空子弹、删除、界面元素列表
                    # 将敌机死亡的数量重新设置为0
                    EnemyPlane.set_enemy_die(True)
                    buttons = game_load(screen)  # 加载登陆界面元素

                    return buttons
                elif 500 <= mouse_y <= 585:  # 按下了退出按钮
                    exit()


def key_load(screen, mouse_x, mouse_y):
    """游戏开始前的设置界面的按键控制函数"""
    for event in pygame.event.get():  # 键盘和鼠标事件的监听
        # 检测是否按了窗口的退出按键
        if event.type == pygame.QUIT:
            sys.exit()
        # 判断是否按下了鼠标并且光标在按钮范围内
        elif event.type == pygame.MOUSEBUTTONDOWN:
            if 220 <= mouse_x <= 420:
                print(mouse_x)
                print(mouse_y)
                if 300 <= mouse_y <= 340:  # 按下了标准模式按钮
                    st.GAME_MOSHI = True
                elif 400 <= mouse_y <= 440:  # 按下了困难模式按钮
                    st.GAME_MOSHI = False
                elif 200 <= mouse_y <= 240:  # 按下了退出按钮
                    exit()

            # 按下了进入游戏按钮
            if 230 <= mouse_x <= 412 and 500 <= mouse_y <= 695:
                print("执行成功")
                cls()  # 清空子弹、删除、界面元素列表
                game_say(screen)  # 加入历史背景界面
                bc(k3=True)  # 游戏历史背景开关打开
                st.ENEMY_MAKE = True  # 重新打开敌机生成器的开关


def key_fight(screen, hero_me):
    """一个战斗界面的按键检测控制函数 """
    for event in pygame.event.get():  # 键盘和鼠标事件的监听
        if event.type == pygame.QUIT:  # 检测是否按了窗口的退出按键
            sys.exit()
        elif event.type == pygame.KEYDOWN:  # 判断是否按下了键盘
            # 是否按下W键或up键
            if event.key == pygame.K_w or event.key == pygame.K_UP:
                st.KEY_UP = True  # 打开开关
            # 是否按下s or down
            elif event.key == pygame.K_s or event.key == pygame.K_DOWN:
                # 打开向下移动的开关
                st.KEY_DOWN = True
            # 是否按下a or left
            elif event.key == pygame.K_a or event.key == pygame.K_LEFT:
                # 打开向左移动的开关
                st.KEY_LEFT = True
            # 是否按下d or right
            elif event.key == pygame.K_d or event.key == pygame.K_RIGHT:
                # 打开向右移动的开关
                st.KEY_RIGHT = True
            # 判断是否按下了Q键
            elif event.key == pygame.K_q:
                bc(k2=True)  # 打开登陆界面开关
                cls()  # 清空子弹、删除、界面元素列表
                # 将敌机死亡的数量重新设置为0
                EnemyPlane.set_enemy_die(True)
                buttons = game_load(screen)  # 加载登陆界面元素
                return buttons

        elif event.type == pygame.KEYUP:  # 是否放开了键盘
            if event.key == pygame.K_w or event.key == pygame.K_UP:
                # 关闭开关
                st.KEY_UP = False
            elif event.key == pygame.K_s or event.key == pygame.K_DOWN:
                # 关闭向下移动的开关
                st.KEY_DOWN = False
            elif event.key == pygame.K_a or event.key == pygame.K_LEFT:
                # 关闭向左移动的开关
                st.KEY_LEFT = False
            elif event.key == pygame.K_d or event.key == pygame.K_RIGHT:
                # 关闭向右移动的开关
                st.KEY_RIGHT = False

        if event.type == pygame.MOUSEBUTTONDOWN:  # 判断是否按下了鼠标
            if hero_me.get_fire():  # 如果发射子弹的开关是打开的
                hero_me.fire()  # 将子弹列表的元素加入显示列表


def go_game_end(screen):
    """游戏结束的界面控制"""
    global fps6
    if st.ENEMY_START and st.BOSS_DIE:  # 如果boss产生了但又死光
        fps6 += 1  # 计数器启动
        if fps6 == 300:
            cls()  # 清空子弹、删除、界面元素列表
            buttons = game_end(screen)  # 加载结束界面
            bc(k5=True)  # 打开结束界面开关
            st.ENEMY_START = False  # 关闭boss检测开关
            st.BOSS_DIE = False  # 关闭boss死光开关
            return buttons


def game_end(screen):
    """对方大boss死亡后出现结束界面"""
    # 创建背景图片
    Factory.beijing_act(0, 0, screen, st.MY_TEXT)
    # 创建退出游戏按钮
    button_4 = Factory.button1_act(20, 500, screen, st.BUTTON_D)
    # 创建重新开始按钮
    button_5 = Factory.button1_act(20, 350, screen, st.BUTTON_E)
    # 创建下一关按钮
    button_6 = Factory.button1_act(20, 200, screen, st.BUTTON_F)
    # 创建积分界面画布
    Factory.beijing_act(640, 0, screen, st.IMAGE_BJ)
    integ(screen)  # 创建统计信息标签
    return button_4, button_5, button_6


def game_say(screen):
    """显示一段文字"""
    # 创建一个星空背景
    Factory.beijing_act(0, 0, screen, st.MY_TEXT)
    text = "公元2300年，外星人入侵,这是人类的最后时刻！"
    Factory.script_act(20, 300, screen, text, 30, num=3,
                       filename=st.SCRIPT, bg_script=(255, 255, 255))


def enemy_make(screen, EnemyCreate):
    """敌机生成控制函数"""
    if st.ENEMY_MAKE:  # 生成器开关默认是打开的
        enemy_plane = None
        stony = None
        try:
            # 若未达到敌机死亡的上限
            if EnemyPlane.get_enemy_die() < st.ENEMY_NUM:
                enemy_plane = next(EnemyCreate)  # 敌机生成
                stony = stony_creat(screen)  # 陨石生成
            else:
                st.BOSS_CREAT = True
                st.ENEMY_MAKE = False  # 关闭生成器的开关
        except StopIteration:
            enemy_plane = None
            stony = None

        try:
            if enemy_plane:  # 如果不为空
                screen_list.append(enemy_plane)  # 加入显示列表

            if stony:  # 如果不为空
                screen_list.append(stony)
        except Exception as re:
            print(re)


def boss_make(screen):
    """敌机boss的生成控制"""
    global fps2
    if st.BOSS_CREAT:  # 创建boss
        fps2 += 1
        # print(fps2)
        if fps2 == 100:
            for i in range(st.BOSS_NUM):
                Factory.enemy_act(300, -200, screen, dict_enemy['2'])
            fps2 = 0
            st.BOSS_CREAT = False  # 关闭创建boss的开关
            st.ENEMY_START = True  # 打开检测boss飞机的开关


def boss_die():
    """所有的boss是否死亡检测"""
    boss_button = True  # 开始默认打开的
    for ele in screen_list:  # 如果遍历一次后发现还存在boss飞机，则关闭
        if isinstance(ele, BossEnemy):
            boss_button = False
    if boss_button:  # 如果没有boss飞机了
        st.BOSS_DIE = True
    return st.BOSS_DIE


def buff_make():
    """各种buff子弹有效时间计数函数"""
    if st.GOD_BUFF:  # 金币子弹buff出现,大于500帧数后消失
        st.BUFF_TIME += 1
        if st.BUFF_TIME >= 500:
            st.GOD_BUFF = False

    if st.LASER_BUFF:  # 激光子弹buff出现，大于500帧数后消失
        st.LASER_TIME += 1
        if st.LASER_TIME >= 500:
            st.LASER_BUFF = False

    if st.RAN_BUFF:  # 随机子弹buff出现
        st.RAN_TIME += 1
        if st.RAN_TIME >= 500:
            st.RAN_BUFF = False


def move_make(dict_key, hero_me):
    """控制飞机移动的方法"""
    global num
    for item in dict_key.items():  # 通过开关控制我方飞机移动
        if item[0]:
            # print(item[0])
            num += 1
            if num > 2:
                hero_me.hreo_move(item[1])
                num = 0


def clear_list():
    """清除相关列表中的元素函数"""
    bullet_list.clear()  # 清除发射出的列表
    bullet_del.clear()  # 清空该删除的列表
    screen_list.clear()  # 清空界面元素


cls = clear_list


def loop():
    """抽取主函数中循环的代码"""
    screen_list.extend(bullet_list)  # 将敌机产生的子弹加入显示列表
    # print(len(bullet_list))
    bullet_list.clear()  # 清除列表

    for bu in bullet_del:  # 从显示列表中删除应该消失的子弹
        if bu in screen_list:
            screen_list.remove(bu)
    bullet_del.clear()  # 清空列表

    for element in screen_list:  # 循环显示所有对象,默认多态
        element.draw()
        # print(len(screen_list))
        # print(screen_list)


def game_load(screen):
    """创建游戏登陆界面需要的图像"""
    # 创建开始界面背景
    Factory.beijing_act(0, 0, screen, st.BEIJING_2)
    # 创建积分界面
    Factory.beijing_act(640, 0, screen, st.IMAGE_BJ)
    # 创建游戏操作说明
    Factory.beijing_act(120, 50, screen, st.FUNCTION_1)
    # 创建标准模式按钮
    button1 = Factory.button1_act(220, 300, screen, st.BUTTON_A)
    # 困难模式按钮
    button2 = Factory.button1_act(220, 400, screen, st.BUTTON_B)
    # 退出按钮
    button3 = Factory.button1_act(220, 200, screen, st.BUTTON_C)
    # 生产一个开始按钮并加入显示列表
    Factory.button_act(230, 500, screen, st.BUTTON_START)

    integ(screen)  # 创建统计信息标签
    Factory.music_act(st.START_MUSIC)  # 游戏的开始音乐
    # print(len(screen_list))
    # print(len(list_game))
    return button1, button2, button3


def integ(screen):
    """创建游戏统计信息的显示文字"""
    # 取得一个随机数
    ran = random.randint(0, 4)
    # 创建角色头像标签
    Factory.beijing_act(640, 0, screen, st.BOY_IMAGE[ran])
    # 创建分数标签
    Factory.script_act(655, 325, screen, "分数", 50,
                       filename=st.SCRIPT, bg_script=(0, 255, 255))
    # 创建角色标签
    Factory.script_act(655, 150, screen, "角色", 50,
                       filename=st.SCRIPT, bg_script=(0, 255, 255))
    # 创建排名标签
    Factory.script_act(655, 500, screen, "排名", 50,
                       filename=st.SCRIPT, bg_script=(0, 255, 255))


def game_before(screen):
    """创建游戏之前的界面图像"""
    # 有主背景图片、飞机大战题目图片、游戏发言图片、作者图片、积分界面图片
    beijing_before = [[0, 0, st.MY_XING],
                      [100, 200, st.MY_READ],
                      [450, 380, st.MY_SELF],
                      [640, 0, st.IMAGE_BJ]
                      ]
    # "保护地球人人有责"的坐标列表
    script_before = ["保", "护", "地", "球", "人", "人", "有", "责"]
    for i, bj in enumerate(beijing_before):
        # 创建所有界面元素并添加
        Factory.beijing_act(bj[0], bj[1], screen, bj[2])
    for j, sb in enumerate(script_before):
        # 创建文字对象
        Factory.script_act(660, 10 + j * 83, screen, sb, 80, filename=st.SCRIPT1)

    Factory.music_act(st.START_MUSIC)  # 创建并播放音乐


def chars(screen):
    """显示“星河战争“四个字的动态效果生成器"""
    list_char = [(120, "星"), (220, "河"), (320, "战"), (420, "争")]

    for tp in list_char:
        # 创建一个文字
        script = Factory.script_act(tp[0], 100, screen, tp[1], 120, num=1, color=(0, 0, 255))
        # 创建一个爆炸
        Factory.any_blast(script, "big", 2)
        yield script


def game_fight(screen):
    """创建游戏战斗需要的图像并加载"""
    # 创建一个战斗界面背景
    beijing_1 = Factory.beijing_act(0, 0, screen, st.BEIJING_1)
    # 创建积分界面
    Factory.beijing_act(640, 0, screen, st.IMAGE_BJ)
    integ(screen)  # 创建统计信息标签
    # 创建我方飞机并设置初始位置
    hero_me = Factory.hreo_act(270, 600, screen, st.HREO_1)
    hero_me.button_fire = True  # 将我方飞机的开火开关打开
    return beijing_1, hero_me


def enemy_create(screen):
    """敌机的生成器,使用了迭代器的方式"""
    i = 0
    while i < 500:
        ran1 = random.randint(0, 2)  # 生成敌机的 出生位置
        ranx = random.randint(0, 20)  # 调整敌机生成的概率
        if ranx <= 14:
            ran2 = 0
        else:
            ran2 = 1
        # 创建敌方飞机
        enemy_plane = EnemyPlane(100 + ran1 * 200, -100, screen, dict_enemy[str(ran2)])
        yield enemy_plane
        i += 1
        # st.BOSS_CREAT = True


def stony_creat(screen):
    """陨石生成器"""
    ran1 = random.randint(0, 2)  # 生成出生位置
    ran2 = random.randint(0, 10)  # 设置出生概率
    if ran2 <= 2:  # 20%的出生概率
        stony_one = Stony(250 + ran1 * 100, -100, screen, st.STONY_BUFF)
        return stony_one
    else:
        return False


def delay_time(delay, time0=time.time()):
    """一个延时函数"""
    time1 = time.time()
    if time1 - time0 >= delay:
        return True
    else:
        return False


if __name__ == '__main__':
    pass
